#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include "home_plus.h"

// global variables
struct sockaddr_in home_plus_addr;
struct sockaddr_in ua_addr;
int ua_sock;
UA_INFO ua;

// send to user agent func
int send_to_ua(const char *data){
	int rc;

	// init buf
	sleep(10);

	// get device input here

	// dealling with keypad data here

	// store data
	// write data into home_buf->msg

	// send data
	rc = sendto(ua_sock, data, strlen(data), 0, (struct sockaddr *)&ua_addr, sizeof(ua_addr));

	if (rc < 0){
		printf("cannot send data \n");
		close(ua_sock);
		exit(1);
	}
	
	return rc;
}

// create client socket func
void create_socket_info(){
	memset((char*) &home_plus_addr, 0, sizeof(home_plus_addr));
	home_plus_addr.sin_family = AF_INET;
	home_plus_addr.sin_addr.s_addr = inet_addr(SERVER);
	home_plus_addr.sin_port = htons(HOME_PLUS_PORT);

	memset((char*) &ua_addr, 0, sizeof(ua_addr));
	ua_addr.sin_family = AF_INET;
	ua_addr.sin_addr.s_addr = inet_addr(UA);
	ua_addr.sin_port = htons(UA_PORT);

	ua_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
}	

// thread functions
void keypad_listener(void * paramsd){
	int sd, rc;
	char buf[MAX_BUF];
	MSG *home_buf;

	// setting socket
	//create_client_socket(&sd);	
	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	printf("keypad thread created(%d)\n", sd);

	// device open and initiation

	// infinite loop
	while(1){
		// init buf
		memset(buf, 0, MAX_BUF);
		sleep(10);

		// get device input here

		// dealling with keypad data here

		// store data
		home_buf = (MSG *)buf;
		// home_buf->cmd = Defined Command;
		// write data into home_buf->msg
		home_buf->cmd = 1;
		sprintf(buf, "test");

		// send data
		rc = sendto(sd, buf, strlen(buf), 0, (struct sockaddr *)&home_plus_addr, sizeof(home_plus_addr));

		if (rc < 0){
			printf("cannot send data \n");
			close(sd);
			exit(1);
		}
	}
	return;
}

void dip_switch_listener(void * paramsd){
	int sd, rc;
	char buf[MAX_BUF];
	MSG *home_buf;

	// setting socket
	//create_client_socket(&sd);	
	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	printf("diq switch thread created(%d)\n", sd);

	// device open and initiation

	// infinite loop
	while(1){
		// init buf
		memset(buf, 0, MAX_BUF);
		sleep(20);

		// get device input here

		// dealling with keypad data here

		// store data
		home_buf = (MSG *)buf;
		// home_buf->cmd = Defined Command;
		// write data into home_buf->msg

		// send data
		rc = sendto(sd, buf, strlen(buf), 0, (struct sockaddr *)&home_plus_addr, sizeof(home_plus_addr));

		if (rc < 0){
			printf("cannot send data \n");
			close(sd);
			exit(1);
		}
	}
	return;
}

void sensor_listener(void * paramsd){
	int sd, rc;
	char buf[MAX_BUF];
	MSG *home_buf;

	int fd,c, res;
	struct termios oldtio,newtio;
	int sid;
	int i;
	int sensor[4][4] = {0};
	int fd2; // 7segment
	int value;

	// setting socket
	//create_client_socket(&sd);	
	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	printf("sensor thread created(%d)\n", sd);

	// device open and initiation
	//7segment
	if((fd2 = open("/dev/7segment",O_RDWR | O_SYNC)) < 0) {
		printf("FND open fail \n");
		exit(1);
	}

	// sensor
	fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
	if (fd <0) {perror(MODEMDEVICE); exit(-1); }

	tcgetattr(fd,&oldtio); /* save current port settings */
	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
	newtio.c_iflag = IGNPAR;
	newtio.c_oflag = 0;

	/* set input mode (non-canonical, no echo,...) */
	newtio.c_lflag = 0;
	newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
	newtio.c_cc[VMIN]     = 43;   /* blocking read until 5 chars received */
	tcflush(fd, TCIFLUSH);
	tcsetattr(fd,TCSANOW,&newtio);

	// infinite loop
	while(1){
		res = read(fd,buf,255);   /* returns after 5 chars have been input */
		buf[res]=0;               /* so we can printf... */

		if(res>43)
			continue;
		sid = buf[8];
		sensor[sid-1][0] = buf[20];
		sensor[sid-1][1] = buf[22];
		sensor[sid-1][2] = buf[24] + (buf[25]*256);
		sensor[sid-1][3] = buf[26];

		value = sensor[sid-1][3];
		write(fd2,&value,4); 

		if(sensor[i][3] < 50){	// invasion
			//Dev_Buzzer();
			// init buf
			memset(buf, 0, MAX_BUF);
			sleep(40);

			// get device input here

			// dealling with keypad data here

			// store data
			home_buf = (MSG *)buf;
			// home_buf->cmd = Defined Command;
			// write data into home_buf->msg

			sprintf(buf, "Allert");

			// send data
			rc = sendto(sd, buf, strlen(buf), 0, (struct sockaddr *)&home_plus_addr, sizeof(home_plus_addr));

			if (rc < 0){
				printf("cannot send data \n");
				close(sd);
				exit(1);
			}
		}	
	}
	// sensor, 7segment
	tcsetattr(fd,TCSANOW,&oldtio);
	return;
}

void ua_listener(void * paramsd){
	int sd, rc;
	char buf[MAX_BUF];
	MSG *home_buf;

	// setting socket
	//create_client_socket(&sd);	
	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	printf("ua thread created(%d)\n", sd);

	// device open and initiation

	// infinite loop
	while(1){
		// init buf
		memset(buf, 0, MAX_BUF);
		sleep(10);

		// get device input here

		// dealling with keypad data here

		// store data
		home_buf = (MSG *)buf;
		// home_buf->cmd = Defined Command;
		// write data into home_buf->msg
		home_buf->cmd = 1;
		sprintf(buf, "ua thread");

		// send data
		rc = sendto(sd, buf, strlen(buf), 0, (struct sockaddr *)&home_plus_addr, sizeof(home_plus_addr));

		if (rc < 0){
			printf("cannot send data \n");
			close(sd);
			exit(1);
		}
	}
	return;
}

// home plus processor
// main()
int main(void){
	int home_plus_sock;
	int addr_len;

	pthread_t keypad_thread;
	pthread_t dip_switch_thread;
	pthread_t sensor_thread;
	pthread_t ua_thread;

	struct sockaddr_in clientAddr;	// home_plus 
	struct sockaddr_in serverAddr;	// home_plus main() addr
	char buf[MAX_BUF];
	MSG *home_buf;
	int rc, n, cliLen;
	int dot_dev, temp=0;
	int dot_value;


	// socket creation
	home_plus_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(home_plus_sock < 0){
		printf("cannot open home plus socket\n");
		exit(1);
	}

	create_socket_info();
	ua.port = 2411;
	sprintf(ua.addr, "127.0.0.1");
	ua.state = ON;	// ON or OFF

	// bind local server port
	memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddr.sin_port = htons(HOME_PLUS_PORT);
	rc = bind(home_plus_sock, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
	if(rc < 0){
		printf("cannot bind port number %d \n", HOME_PLUS_PORT);
		exit(1);
	}

	// create threads
	// create keypad listener thread
	pthread_create(&keypad_thread, 0, (void*)keypad_listener, (void *) home_plus_sock);
	// create dip switch listener thread
//	pthread_create(&dip_switch_thread, 0, (void*)dip_switch_listener, (void *) home_plus_sock);
	// create sensor listener thread
//	pthread_create(&sensor_thread, 0, (void*)sensor_listener, (void *) home_plus_sock);
	// create user agent listener thread 
//	pthread_create(&ua_thread, 0, (void*)ua_listener, (void *) home_plus_sock);

	// init devices
	// Dot
	if(dot_dev = open("/dev/dotmatrix", O_WRONLY) == -1){
		// error
		printf("Error: Dotmatrix Open ERROR!\n");
		exit(1);
	}
	//write(dot_dev, &dot_value, 4); // dot_value = integer
	
	// LED

	// home plus infinite loop
	while(1){
		// init buffer
		memset(buf, 0, MAX_BUF);

		// receive message
		cliLen = sizeof(clientAddr);
		n = recvfrom(home_plus_sock, buf, MAX_BUF, 0, (struct sockaddr *)&clientAddr, &cliLen);
		home_buf = (MSG *)buf;

		if(n < 0){
			printf("cannot receive data\n");
			continue;
		}

		// received message complete

		// cmd check

		// do appropriate work here for each cmd
		printf("cmd : [], msg : [%s]\n", buf);

		// dotmatrix test.
		dot_value = COME_BACK_HOME;
		write(dot_dev, &dot_value, 4);
	}

	return 0;
}
